/*
 * AODV协议教学测试程序
 * 这个程序专门用于演示和学习AODV协议的各个功能
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "aodv_socket.h"
#include "aodv_packet.h"
#include "aodv_types.h"
#include "aodv_routing_table.h"
#include "aodv_rreq.h"
#include "aodv_rrep.h"
#include "aodv_rerr.h"
#include "aodv_forward.h"
#include "aodv_hello.h"

// 测试函数声明
void test_routing_table_operations();
void test_rreq_functionality();
void test_rrep_functionality();
void test_data_forwarding();
void test_rerr_handling();
void test_hello_mechanism();
void print_test_header(const char* test_name);
void print_test_result(const char* test_item, int passed);

// 全局测试统计
int tests_run = 0;
int tests_passed = 0;

int main() {
    printf("==========================================\n");
    printf("     AODV协议功能测试教学程序\n");
    printf("==========================================\n\n");
    
    // 初始化Winsock
    printf("1. 初始化网络环境...\n");
    if (aodv_socket_init() != 0) {
        fprintf(stderr, "❌ Winsock初始化失败\n");
        return 1;
    }
    printf("✅ 网络环境初始化成功\n\n");
    
    // 运行各项测试
    test_routing_table_operations();
    test_rreq_functionality();
    test_rrep_functionality();
    test_data_forwarding();
    test_rerr_handling();
    test_hello_mechanism();
    
    // 打印测试总结
    printf("\n==========================================\n");
    printf("           测试总结报告\n");
    printf("==========================================\n");
    printf("总测试项: %d\n", tests_run);
    printf("通过测试: %d\n", tests_passed);
    printf("失败测试: %d\n", tests_run - tests_passed);
    printf("测试通过率: %.1f%%\n", (tests_passed * 100.0) / tests_run);
    printf("==========================================\n");
    
    // 清理
    aodv_socket_cleanup();
    return (tests_passed == tests_run) ? 0 : 1;
}

void print_test_header(const char* test_name) {
    printf("\n🔍 %s\n", test_name);
    printf("----------------------------------------\n");
}

void print_test_result(const char* test_item, int passed) {
    tests_run++;
    if (passed) {
        tests_passed++;
        printf("✅ %s\n", test_item);
    } else {
        printf("❌ %s\n", test_item);
    }
}

// 测试1：路由表操作
void test_routing_table_operations() {
    print_test_header("路由表操作测试");
    
    aodv_routing_table routing_table;
    routing_table_init(&routing_table);
    
    // 测试1.1：添加路由条目
    routing_table_entry entry = {
        .dest_addr = inet_addr("192.168.1.100"),
        .dest_seq_num = 10,
        .next_hop_addr = inet_addr("192.168.1.1"),
        .hop_count = 2,
        .lifetime = (uint32_t)time(NULL) + 300
    };
    
    int result1 = routing_table_add_or_update(&routing_table, &entry);
    print_test_result("添加路由条目", result1 == 0);
    
    // 测试1.2：查找路由
    routing_table_entry* found = routing_table_find(&routing_table, inet_addr("192.168.1.100"));
    print_test_result("查找存在的路由", found != NULL);
    
    // 测试1.3：查找不存在的路由
    routing_table_entry* not_found = routing_table_find(&routing_table, inet_addr("10.0.0.1"));
    print_test_result("查找不存在的路由", not_found == NULL);
    
    // 测试1.4：路由有效性检查
    int is_valid = routing_table_is_valid(&routing_table, inet_addr("192.168.1.100"));
    print_test_result("检查有效路由", is_valid == 1);
    
    printf("\n当前路由表状态:\n");
    routing_table_print(&routing_table);
}

// 测试2：RREQ功能测试
void test_rreq_functionality() {
    print_test_header("RREQ功能测试");
    
    // 创建测试环境
    aodv_routing_table routing_table;
    routing_table_init(&routing_table);
    rreq_id_cache rreq_cache;
    rreq_id_cache_init(&rreq_cache);
    
    // 添加一个已知路由用于测试
    routing_table_entry known_route = {
        .dest_addr = inet_addr("192.168.1.50"),
        .dest_seq_num = 5,
        .next_hop_addr = inet_addr("192.168.1.50"),
        .hop_count = 1,
        .lifetime = (uint32_t)time(NULL) + 300
    };
    routing_table_add_or_update(&routing_table, &known_route);
    
    // 测试2.1：RREQ消息构建
    aodv_rreq test_rreq;
    int build_result = build_rreq_packet(&test_rreq, 123, inet_addr("192.168.1.10"), 
                                        5, inet_addr("192.168.1.20"), 2, 0);
    print_test_result("构建RREQ消息", build_result == 0);
    
    // 测试2.2：RREQ消息验证（检查基本字段）
    int is_valid = (test_rreq.header.type == AODV_RREQ && test_rreq.rreq_id > 0);
    print_test_result("验证RREQ消息", is_valid == 1);
    
    // 测试2.3：RREQ ID缓存
    rreq_id_cache_add(&rreq_cache, inet_addr("192.168.1.20"), 123);
    int cache_contains = rreq_id_cache_contains(&rreq_cache, inet_addr("192.168.1.20"), 123);
    print_test_result("RREQ ID缓存功能", cache_contains == 1);
    
    printf("\nRREQ消息内容:\n");
    printf("- RREQ ID: %u\n", test_rreq.rreq_id);
    printf("- 源地址: %s\n", inet_ntoa(*(struct in_addr*)&test_rreq.orig_addr));
    printf("- 目标地址: %s\n", inet_ntoa(*(struct in_addr*)&test_rreq.dest_addr));
    printf("- 序列号: %u\n", test_rreq.dest_seq_num);
}

// 测试3：RREP功能测试
void test_rrep_functionality() {
    print_test_header("RREP功能测试");
    
    aodv_routing_table routing_table;
    routing_table_init(&routing_table);
    
    // 测试3.1：RREP消息构建
    aodv_rrep test_rrep;
    int build_result = build_rrep_packet(&test_rrep, inet_addr("192.168.1.100"), 20,
                                        inet_addr("192.168.1.1"), 3, 2, 5000);
    print_test_result("构建RREP消息", build_result == 0);
    
    // 测试3.2：RREP消息验证
    int validate_result = is_valid_rrep(&test_rrep);
    print_test_result("验证RREP消息", validate_result == 1);
    
    // 测试3.3：无效RREP（跳数过多）
    aodv_rrep invalid_rrep;
    build_rrep_packet(&invalid_rrep, inet_addr("192.168.1.200"), 25,
                     inet_addr("192.168.1.1"), 10, 44, 500); // 跳数=44（合理）
    int invalid_result = is_valid_rrep(&invalid_rrep);
    print_test_result("检测无效RREP（跳数过多）", invalid_result == 0);
    
    printf("\nRREP消息内容:\n");
    printf("- 目标地址: %s\n", inet_ntoa(*(struct in_addr*)&test_rrep.dest_addr));
    printf("- 目标序列号: %u\n", test_rrep.dest_seq_num);
    printf("- 跳数: %u\n", test_rrep.hop_count);
    printf("- 生存时间: %u ms\n", test_rrep.lifetime);
}

// 测试4：数据转发功能测试
void test_data_forwarding() {
    print_test_header("数据转发功能测试");
    
    // 注意：由于需要实际的网络套接字，这里主要测试逻辑功能
    aodv_routing_table routing_table;
    routing_table_init(&routing_table);
    
    // 添加测试路由
    routing_table_entry route1 = {
        .dest_addr = inet_addr("10.0.0.100"),
        .dest_seq_num = 15,
        .next_hop_addr = inet_addr("10.0.0.100"),
        .hop_count = 1,
        .lifetime = (uint32_t)time(NULL) + 300
    };
    routing_table_add_or_update(&routing_table, &route1);
    
    // 测试数据包头部构建
    data_packet_header_t header;
    header.dest_addr = inet_addr("10.0.0.100");
    header.src_addr = inet_addr("192.168.1.1");
    header.packet_id = 12345;
    header.packet_type = PACKET_TYPE_DATA;
    header.data_len = 50;
    header.timestamp = (uint32_t)time(NULL);
    
    print_test_result("构建数据包头部", 1);
    
    // 测试路由查找
    routing_table_entry* route = routing_table_find(&routing_table, inet_addr("10.0.0.100"));
    print_test_result("查找转发路由", route != NULL);
    
    // 测试未知目标
    routing_table_entry* unknown_route = routing_table_find(&routing_table, inet_addr("172.16.0.1"));
    print_test_result("处理未知目标（应触发路由发现）", unknown_route == NULL);
}

// 测试5：RERR消息处理测试
void test_rerr_handling() {
    print_test_header("RERR消息处理测试");
    
    aodv_routing_table routing_table;
    routing_table_init(&routing_table);
    
    // 添加一个路由，稍后会被RERR标记为无效
    routing_table_entry route = {
        .dest_addr = inet_addr("172.16.1.100"),
        .dest_seq_num = 30,
        .next_hop_addr = inet_addr("172.16.1.1"),
        .hop_count = 3,
        .lifetime = (uint32_t)time(NULL) + 300
    };
    routing_table_add_or_update(&routing_table, &route);
    
    // 测试5.1：RERR消息构建
    aodv_rerr test_rerr;
    build_rerr_packet_with_type(&test_rerr, inet_addr("172.16.1.100"), 35, RERR_DEST_UNREACHABLE);
    print_test_result("构建RERR消息", 1);
    
    // 测试5.2：RERR消息验证
    int validate_result = validate_rerr_message(&test_rerr);
    print_test_result("验证RERR消息", validate_result == 1);
    
    printf("\nRERR消息内容:\n");
    printf("- RERR包类型: %d\n", test_rerr.header.type);
    printf("- 不可达目的数量: %d\n", test_rerr.dest_count);
}

// 测试6：Hello机制测试
void test_hello_mechanism() {
    print_test_header("Hello机制测试");
    
    aodv_routing_table routing_table;
    routing_table_init(&routing_table);
    
    // 测试6.1：Hello消息构建
    aodv_hello test_hello;
    int build_result = build_hello_packet(&test_hello, 5000); // 5秒生命周期
    print_test_result("构建Hello消息", build_result == 0);
    
    // 测试6.2：Hello消息验证
    int validate_result = validate_hello_message(&test_hello, sizeof(aodv_hello));
    print_test_result("验证Hello消息", validate_result == 1);
    
    // 测试6.3：处理Hello消息（模拟添加邻居）
    // 注意：这里简化处理，实际应该通过套接字接收
    printf("模拟处理Hello消息，添加邻居节点...\n");
    routing_table_entry neighbor_route = {
        .dest_addr = inet_addr("192.168.1.50"),
        .dest_seq_num = 10,
        .next_hop_addr = inet_addr("192.168.1.50"),
        .hop_count = 1,  // 直接邻居
        .lifetime = (uint32_t)time(NULL) + (test_hello.lifetime / 1000)
    };
    routing_table_add_or_update(&routing_table, &neighbor_route);
    
    routing_table_entry* neighbor = routing_table_find(&routing_table, inet_addr("192.168.1.50"));
    print_test_result("Hello消息添加邻居", neighbor != NULL && neighbor->hop_count == 1);
    
    // 测试6.4：邻居超时检查
    printf("\n测试邻居超时机制:\n");
    routing_table_entry old_neighbor = {
        .dest_addr = inet_addr("192.168.1.99"),
        .dest_seq_num = 5,
        .next_hop_addr = inet_addr("192.168.1.99"),
        .hop_count = 1,
        .lifetime = (uint32_t)time(NULL) - 10  // 已过期
    };
    routing_table_add_or_update(&routing_table, &old_neighbor);
    
    // 执行超时检查
    check_neighbor_timeout(&routing_table, inet_addr("192.168.1.1"), (uint32_t)time(NULL));
    
    routing_table_entry* expired_neighbor = routing_table_find(&routing_table, inet_addr("192.168.1.99"));
    print_test_result("过期邻居清理", expired_neighbor == NULL);
    
    printf("\nHello消息内容:\n");
    printf("- Hello包类型: %d\n", test_hello.header.type);
    printf("- Hello生命周期: %u\n", test_hello.lifetime);
}